<?php
class Dispatcher {

	const ID_DEF_APP = "index";
	const ID_DEF_ENT = "index";
	const ID_DEF_ACT = "index";
	const ID_URL_LANG = "hl";
	const ID_SESS_LANG = "session_hl";
	
	const DEFF_LANG_ID = "en";
	
	var $appConfig = null;
	var $debugFlag = false;
	
	public function __construct($app_config) {
		import("apps.EmptyApp");
		
		$this->appConfig = $app_config;
	}
	
	function delegate() {
		//
		// Set language
		//
		import('Language');
		import('data.logic.lingvo.Bundle');
		
		$lang_id = @$_COOKIE[self::ID_SESS_LANG];
		if (isset($_GET[self::ID_URL_LANG])) {
			$lang_id = $_GET[self::ID_URL_LANG];
			$_SESSION[self::ID_SESS_LANG] = $lang_id;
			setcookie(self::ID_SESS_LANG, $lang_id, time()+604800,"/");
		}
		if ($lang_id==null && isset($_SESSION[self::ID_SESS_LANG])) $lang_id = $_SESSION[self::ID_SESS_LANG];
		if ($lang_id==null) $lang_id = self::DEFF_LANG_ID;
		$language = new Language($lang_id);
		$GLOBALS[Bundle::KEY] = &$language;
		
		if ($this->debugFlag) {
			print "language id = ".$lang_id."\n";
		}
		
		//
		// load resource files
		//
		$resClazz = null;
		$mr = $this->appConfig->getMessagesResource();
		if ($mr) {
			try {
				$resClazz = import($mr."_".$lang_id);
			} catch (Exception $e) {
			}
			if (!$resClazz) try {
				$resClazz = import($mr."_".self::DEFF_LANG_ID);
			} catch (Exception $e) {
			}
			if ($resClazz)	
				$language->setResource(new $resClazz());
			if ($this->debugFlag) {
				print "resource file = ".$resClazz."\n";
			}
		}
		
			
		//
		// prepare route
		//
		$route = (empty($_GET['route'])) ? '' : $_GET['route'];
		if (empty($route)) { $route = 'index'; }
		
		// Get separate parts
		$parts = explode('/', trim($route, '/\\'));
		
		$appname = array_shift($parts);
		$entity = array_shift($parts);
		$action = array_shift($parts);

		if (empty($appname) || empty($entity)) {
			$p = explode(".", (string)$this->appConfig->getDefaultApp(), 3);
			$appname = $p[0];
			$entity = $p[1];
			if (isset($p[2])) $action = $p[2];
		}
		if (empty($action)) { $action = self::ID_DEF_ACT; }
		if ($this->debugFlag) {
			print "parts of URI: app = ".$appname.", entity=".$entity.", action=".$action."\n";
		}
		
		
		
		//
		// Configure AEM
		//
		$application = null;
		$controller = null;
		$method = null;
		$x_app = $this->appConfig->getApp($appname);
		if ($x_app) {
			// Application configure
			$application = $x_app['id'];
			if ($this->debugFlag) {
				print "application = ".$x_app['id']."\n";
			}
			
			// Entity configure
			$x_entity = $this->appConfig->getEntity($appname, $entity);
			if ($x_entity) {
				// Find right controller
				try {
					if (!isset($x_entity["class"]) || strlen((string)$x_entity["class"])==0) 
						throw new Exception("Class is empty");
						
					$clazz = import((string)$x_entity["class"]);
					$controller = new $clazz();
					
					if (!isset($controller)) 
						throw new Exception("Class '".(string)$x_entity["class"]."' not found");
					if ($this->debugFlag) {
						print "controller = ".$clazz."\n";
					}
				} catch (Exception $e) {
					echo 'Caught exception: ',  $e->getMessage(), "\n";
					die();
				}
				
				
				
				// Method configure
				$x_action = $this->appConfig->getAction($appname, $entity, $action);
				if ($x_action) {
					import("mvc.AppMapping");
					$mapping = new AppMapping();
			
					// forward for current action
					$frws = array();
					if (isset($x_action) && is_object($x_action->forward)) {
						import("mvc.AppForward");
						foreach ($x_action->forward as $forward) {
							$frws[(string)$forward["name"]] = new AppForward((string)$forward["path"]);
						}
					}
					$mapping->setForwards($frws);
				
					if ($x_action["form"]) {
						if ($form = $this->appConfig->getForm((string)$x_action["form"]))
							try {
								$clazz = import((string)$form["class"]);
								$mapping->setForm(new $clazz((string)$form["name"]));
							} catch (Exception $e) {
								echo 'Caught exception: ',  $e->getMessage(), "\n";
							}
					}
					
					$method = ((string)$x_action["method"] ? (string)$x_action["method"] : (string)$x_action["id"]);
					if ($this->debugFlag) {
						print "method = ".$method."\n";
					}
				} //x_action
			} //x_entity
		} //x_app
		

		if ($application && $controller && $method) {
			$controller->setLanguage($language);
			
	    	import("net.http.HttpRequest");
			import("net.http.HttpResponse");
			$request = new HttpRequest();
			$request->setMethod($_SERVER["REQUEST_METHOD"]);
			
			$response = null;
			
			import('net.html.form.ActionErrors');
	    	$errors = new ActionErrors();
	    	$controller->setErrors($errors);
	    	//$this->messages = new ActionErrors();
			
			import('smarty.Smarty');
		    $smarty=new Smarty;
		    $smarty->use_sub_dirs = false;
		    $smarty->template_dir = APPSERVER_ROOT. "/WEB-INF/templates";
		    $smarty->compile_dir  = APPSERVER_ROOT. "/WEB-INF/templates_c";
	
		    $smarty->assign_by_ref("lang", $language);
		    $smarty->assign_by_ref("language", $language);
		    $smarty->assign_by_ref("errors", $errors);
		    //$smarty->assign_by_ref("messages", $this->messages);
		    $smarty->assign_by_ref("controller", $controller);
			    
			
			import("mvc.Context");
			// initialize controller
			$controller->initialize($x_app, $x_entity, $x_action, new Context($request, $smarty, $this->appConfig));
			
			//Run action
			//TODO: move all objects to context	
			$forward = $controller->executeMethod($method, $mapping, $request, $response, $smarty);
			
			if (!$forward) {
				if ($form = $mapping->getForm()) {
			    	// generate form elements and assign to templates
					$smarty->assign("forms", array($form->getName()=>$form->toArray()) );
				}
				
				if ($x_action["template"]) {
					$smarty->display((string)$x_action["template"]);
				}
				if ($controller->logger)
					$controller->logger->close();
			} else {
				$path = "/".str_replace(".","/",$forward->getPath());
				header("Location: $path");
			}
		} else {
			die("Incorrect URI");
		}
	}
}
?>